package com.zhl.common.utils;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.zhl.common.configuration.TencentProperties;
import com.zhl.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Base64;
import java.util.Date;
import java.util.List;

/**
 * @description TODO
 * @Author: z156940l@outlook.com
 * @className COSUtils
 * @Date: 2024/7/21 14:13
 */
@Slf4j
public class COSUtils {

    private final TencentProperties tencentCos;

    public COSUtils(TencentProperties tencentCos){
        this.tencentCos = tencentCos;
    }

    private COSClient cosClient;

    public static final String COS_ATTACHMENT = "attachment";

    /**
     * 创建连接
     */
    private void initCos() {
        try {
            log.info("Cos client init start");
            BasicCOSCredentials cosCredentials = new BasicCOSCredentials(tencentCos.getSecretId(), tencentCos.getSecretKey());
            // 设置 bucket 的地域
            // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分
            //COS_REGION 参数：配置成存储桶 bucket 的实际地域，例如 ap-beijing，更多 COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
            ClientConfig clientConfig = new ClientConfig(new Region(tencentCos.getRegion()));
            // 生成 cos 客户端
            cosClient = new COSClient(cosCredentials, clientConfig);
            if (!cosClient.doesBucketExist(tencentCos.getCosBucket())) {
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(tencentCos.getCosBucket());
                // 设置 bucket 的权限为 Private(私有读写)、其他可选有 PublicRead（公有读私有写）、PublicReadWrite（公有读写）
                createBucketRequest.setCannedAcl(CannedAccessControlList.Private);
            }
            log.info("oss bucket created success!");
        } catch (CosServiceException serverException) {
            serverException.printStackTrace();
            log.error(serverException.toString());
        } catch (CosClientException clientException) {
            clientException.printStackTrace();
            log.error(clientException.toString());
        }
    }

    /**
     * 关闭连接
     */
    private void closeOssClient() {
        try {
            cosClient.shutdown();
        } catch (CosClientException e) {
            log.error(e.toString());
        }
    }

    /**
     * 上传文件
     *
     * @param base64
     * @param originalFilename
     * @return
     */
    public String uploadInputStream(String base64, String originalFilename) {
        File localFile = null;
        String[] filename = null;
        try {
            log.info("fileName = {}", originalFilename);
            filename = originalFilename.split("\\.");
            localFile = base642File(originalFilename, base64);
            localFile.deleteOnExit();
        } catch (IOException e) {
            log.info("File transfer file IOException ={}", e.getMessage());
            //文件上传失败就返回错误响应
            throw new BusinessException("上传失败!");
        }
        if (localFile == null) {
            throw new BusinessException("临时文件为空！");
        }
        //2.【将文件上传到腾讯云】
        initCos();
        // PutObjectRequest(参数1,参数2,参数3)参数1:存储桶,参数2:指定腾讯云的上传文件路径,参数3:要上传的文件
        String key = COS_ATTACHMENT + "/" + new Date().getTime() + "." + filename[1];
        //String key = baseUrl + "/" + originalFilename;
        log.info("key = {}", key);
        PutObjectRequest putObjectRequest = new PutObjectRequest(tencentCos.getCosBucket(), key, localFile);
        //设置存储类型 默认标准型
        putObjectRequest.setStorageClass(StorageClass.Standard);
        //获得到客户端
        try {
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
            String eTag = putObjectResult.getETag();
            log.info("eTag = {}", eTag);
        } catch (CosServiceException e) {
            log.error("CosServiceException ={}", e.getMessage());
            throw new CosServiceException(e.getMessage());
        } catch (CosClientException e) {
            log.error("CosClientException ={}", e.getMessage());
            throw new CosClientException(e.getMessage());
        }
        closeOssClient();
        return tencentCos.getCosBaseUrl() + "/" + key;
    }

    /**
     * 查询对象列表
     */
    public void queryCOSList() {
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
        // 设置 bucket 名称
        listObjectsRequest.setBucketName(tencentCos.getCosBucket());
        // prefix 表示列出的 object 的 key 以 prefix 开始
        listObjectsRequest.setPrefix("images/");
        // deliter 表示分隔符, 设置为/表示列出当前目录下的 object, 设置为空表示列出所有的 object
        listObjectsRequest.setDelimiter("/");
        // 设置最大遍历出多少个对象, 一次 listobject 最大支持1000
        listObjectsRequest.setMaxKeys(1000);
        ObjectListing objectListing = null;
        do {
            try {
                objectListing = cosClient.listObjects(listObjectsRequest);
            } catch (CosServiceException e) {
                e.printStackTrace();
                return;
            } catch (CosClientException e) {
                e.printStackTrace();
                return;
            }
            // common prefix 表示表示被 delimiter 截断的路径, 如 delimter 设置为/, common prefix 则表示所有子目录的路径
            List<String> commonPrefixs = objectListing.getCommonPrefixes();

            // object summary 表示所有列出的 object 列表
            List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries();
            for (COSObjectSummary cosObjectSummary : cosObjectSummaries) {
                // 文件的路径 key
                String key = cosObjectSummary.getKey();
                // 文件的 etag
                String etag = cosObjectSummary.getETag();
                // 文件的长度
                long fileSize = cosObjectSummary.getSize();
                // 文件的存储类型
                String storageClasses = cosObjectSummary.getStorageClass();
            }
            String nextMarker = objectListing.getNextMarker();
            listObjectsRequest.setMarker(nextMarker);
        } while (objectListing.isTruncated());
    }

    /**
     * 获取访问路径
     *
     * @param key
     * @return
     */
    public String showObj(String key) {
        initCos();
        URL objectUrl = cosClient.getObjectUrl(tencentCos.getCosBucket(), key);
        closeOssClient();
        return objectUrl.toString();
    }

    /**
     * base64转file
     *
     * @param fileName
     * @param base64
     * @return
     */
    private File base642File(String fileName, String base64) throws IOException {
        base64 = base64.replaceAll("[\\s*\t\n\r]", "");
        // 解码Base64字符串为字节数组
        byte[] decodedBytes = Base64.getDecoder().decode(base64);
        // 创建临时文件并写入字节数据
        File tempFile = File.createTempFile("temp", fileName);
        FileOutputStream outputStream = new FileOutputStream(tempFile);
        outputStream.write(decodedBytes);
        outputStream.close();
        return tempFile;
    }
}
